<template>
  <div>
    <el-table ref="elTable" :border="true" v-bind="getBindValue" @header-dragend="headerDragend">
      <!-- 多选 -->
      <el-table-column v-if="selection" type="selection" :reserve-selection="reserveSelection" width="40" />
      <template v-for="item in columns">
        <!-- 自定义索引 -->
        <template v-if="item.type === 'index'">
          <el-table-column :key="item[item.field]" v-bind="{ ...getItemBindValue(item) }" type="index" :index="item.index" />
        </template>

        <!-- 树型数据 -->
        <template v-else-if="item.children && item.children.length">
          <table-column :key="item[item.field]" :child="item" />
        </template>

        <template v-else>
          <el-table-column :key="item[item.field]" v-bind="{ ...getItemBindValue(item) }" :prop="item.field">
            <!-- 表头插槽 -->
            <template v-if="item.slots && item.slots.header" #header="scope">
              <table-slot
                v-if="item.slots && item.slots.header"
                :slot-name="item.slots.header"
                :column="item"
                :index="scope.$index"
              />
            </template>

            <!-- 表格内容插槽自定义 -->
            <template v-if="item.slots && item.slots.default" #default="scope">
              <table-slot
                v-if="item.slots && item.slots.default"
                :slot-name="item.slots.default"
                :row="scope.row"
                :column="item"
                :index="scope.$index"
              />
            </template>
          </el-table-column>
        </template>
      </template>
    </el-table>

    <div v-if="pagination" class="pagination__wrap">
      <el-pagination
        :style="paginationStyle"
        :page-sizes="[10, 20, 30, 40, 50, 100]"
        layout="total, sizes, prev, pager, next, jumper"
        v-bind="getPaginationBindValue"
      />
    </div>
  </div>
</template>

<script>
  import { defineComponent, PropType, computed, provide, getCurrentInstance, ref, unref } from 'vue'
  import { deepClone } from '@/utils'
  import { isObject } from '@/utils/is'
  import TableColumn from './components/TableColumn.vue'
  import TableSlot from './components/Slot.vue'
  export default defineComponent({
    name: 'ComTable',
    components: {
      TableSlot,
      TableColumn,
    },
    props: {
      // 表头
      columns: {
        type: Array,
        default: () => [],
      },
      // 是否多选
      selection: {
        type: Boolean,
        default: false,
      },
      // 是否展示分页
      pagination: {
        type: [Boolean, Object],
        default: false,
      },
      // 仅对 type=selection 的列有效，类型为 Boolean，为 true 则会在数据更新之后保留之前选中的数据（需指定 row-key）
      reserveSelection: {
        type: Boolean,
        default: false,
      },
    },
    setup(props, { attrs, slots }) {
      const elTable = (ref < HTMLElement) | (null > null)
      function getTableRef() {
        return unref(elTable)
      }

      const _this = getCurrentInstance()
      provide('tableRoot', _this)

      const getBindValue = computed(() => {
        const bindValue = { ...attrs, ...props }
        delete bindValue.columns
        return bindValue
      })

      function getItemBindValue(item) {
        const delArr = []
        const obj = deepClone(item)
        for (const key in obj) {
          if (delArr.indexOf(key) !== -1) {
            delete obj[key]
          }
        }
        return obj
      }

      const getPaginationBindValue = computed(() => {
        const PaginationBindValue = props.pagination && isObject(props.pagination) ? { ...props.pagination } : {}
        return PaginationBindValue
      })

      const paginationStyle = computed(() => {
        return {
          textAlign: (props.pagination && props.pagination.position) || 'right',
        }
      })

      function headerDragend(newWidth, oldWidth, column) {
        // 不懂为啥无法自动计算宽度，只能手动去计算了。。失望ing，到时候看看能不能优化吧。
        const htmlArr = document.getElementsByClassName(column.id)
        for (const v of htmlArr) {
          if (v.firstElementChild) {
            v.firstElementChild.style.width = newWidth + 'px'
          }
        }
      }

      return {
        elTable,
        getBindValue,
        getItemBindValue,
        slots,
        getTableRef,
        getPaginationBindValue,
        paginationStyle,
        headerDragend,
      }
    },
  })
</script>

<style lang="scss" scoped>
  .pagination__wrap {
    margin-top: 15px;
    background: #fff;
    padding: 10px;
  }
</style>
